#include "recv_handle.h"

extern uint16_t time_period;
extern uint16_t send_type;
extern uint16_t flush_flag;
extern msgbuf_t send_buf;
extern MQTTClient client; // 添加MQTT客户端作为全局变量

// 历史上报回调函数
int report_callback(void *data, int argc, char **argv, char **azColName)
{
    cJSON *data_array = (cJSON *)data;
    cJSON *item = cJSON_CreateObject();

    cJSON_AddStringToObject(item, "value", argv[1]);
    cJSON_AddNumberToObject(item, "time", atol(argv[2]));
    cJSON_AddItemToArray(data_array, item);
    return 0;
}

// 直接发送历史上报数据到MQTT
void send_history_report_directly(const char *report_data)
{
    if (!report_data || strlen(report_data) == 0)
    {
        printf("No history data to send\n");
        return;
    }

    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    int rc;

    pubmsg.payload = (void *)report_data;
    pubmsg.payloadlen = (int)strlen(report_data);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;

    MQTTClient_publishMessage(client, TOPIC1, &pubmsg, &token);
    rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);

    if (rc == MQTTCLIENT_SUCCESS)
    {
        printf("---------历史上报完成--------\n");
    }
    else
    {
        printf("---------历史上报失败--------\n");
    }
}

// 接收到消息处理函数
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    char *payloadptr;
    if (message == NULL || message->payload == NULL)
    {
        printf("Error: Null message or payload received\n");
        return -1;
    }

    payloadptr = message->payload; // 获取消息内容

    cJSON *root = cJSON_Parse(payloadptr); // 解析JSON字符串
    if (root == NULL)
    {
        printf("Invalid JSON received: %.*s\n", (int)message->payloadlen, payloadptr);
        MQTTClient_freeMessage(&message);
        MQTTClient_free(topicName);
        return -1;
    }
    printf("接收到消息: %.*s\n", (int)message->payloadlen, payloadptr);

    if (cJSON_HasObjectItem(root, "report"))
    {
        cJSON *report = cJSON_GetObjectItem(root, "report");
        if (report == NULL)
        {
            printf("Failed to get 'report' from JSON.\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
        cJSON *type = cJSON_GetObjectItem(report, "type");
        if (type == NULL)
        {
            printf("Report type is missing\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }

        switch (type->valueint) // 根据report中type的值进行处理
        {
        case 0:
            printf("刷新上报\n");
            send_type = 0;
            break;
        case 1:
            printf("变化上报\n");
            send_type = 1;
            break;
        case 2:
            printf("周期上报\n");
            cJSON *period = cJSON_GetObjectItem(report, "period");
            if (period != NULL)
                time_period = period->valueint;
            send_type = 2;
            break;
        default:
            printf("Unknown report value: %d\n", type->valueint);
            break;
        }
    }
    else if (cJSON_HasObjectItem(root, "history"))
    {
        printf("历史消息上报\n");
        cJSON *history = cJSON_GetObjectItem(root, "history");
        if (history == NULL)
        {
            printf("Failed to get 'history' from JSON.\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }

        // 直接处理并发送历史上报
        history_report(history);
    }
    else if (cJSON_HasObjectItem(root, "fflush"))
    {
        printf("----------进入刷新-----------\n");
        cJSON *fflush = cJSON_GetObjectItem(root, "fflush");
        if (fflush != NULL && fflush->valueint == 1)
            flush_flag = 1; // 设置刷新标志
    }
    else if (cJSON_HasObjectItem(root, "stm32"))
    {
        send_buf.mtype = 1; // 设置消息类型
        cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
        if (stm32 == NULL)
        {
            printf("Failed to get 'stm32' from JSON.\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
        cJSON *stm_key = cJSON_GetObjectItem(stm32, "key");
        cJSON *stm_value = cJSON_GetObjectItem(stm32, "value");
        if (stm_key == NULL || stm_value == NULL)
        {
            printf("Missing 'key' or 'value' in stm32 object\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
        send_buf.mkey = stm_key->valueint;                                           // 设置设备标识
        strncpy(send_buf.value, stm_value->valuestring, sizeof(send_buf.value) - 1); // 设置设备状态
        send_buf.value[sizeof(send_buf.value) - 1] = '\0';                           // 确保字符串结束

        printf("stm32: key=%d, value=%s\n", send_buf.mkey, send_buf.value);
        if (msg_queue_send("msg_stm", &send_buf, sizeof(send_buf), 0) < 0) // 发送消息到消息队列
        {
            printf("msg_queue_send error\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
    }
    else if (cJSON_HasObjectItem(root, "modbus")) // 处理modbus数据
    {
        cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
        if (modbus == NULL)
        {
            printf("Failed to get 'modbus' from JSON.\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
        cJSON *modbus_key = cJSON_GetObjectItem(modbus, "key");
        cJSON *value = cJSON_GetObjectItem(modbus, "value");
        cJSON *addr = cJSON_GetObjectItem(modbus, "addr");
        if (modbus_key == NULL || value == NULL || addr == NULL)
        {
            printf("Missing 'key', 'value' or 'addr' in modbus object\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
        send_buf.mkey = modbus_key->valueint;
        strncpy(send_buf.value, value->valuestring, sizeof(send_buf.value) - 1);
        send_buf.value[sizeof(send_buf.value) - 1] = '\0';
        send_buf.addr = addr->valueint;
        send_buf.mtype = 2; // 设置消息类型
        if (msg_queue_send("msg_mod", &send_buf, sizeof(send_buf), 0) < 0)
        {
            printf("msg_queue_send error\n");
            cJSON_Delete(root);
            MQTTClient_freeMessage(&message);
            MQTTClient_free(topicName);
            return -1;
        }
    }

    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    cJSON_Delete(root);
    return 1;
}

void history_report(cJSON *history_obj)
{
    sqlite3 *db;
    char *errmsg = NULL;
    char sql[256] = "";

    // 从history对象中获取data对象
    cJSON *data = cJSON_GetObjectItem(history_obj, "data");
    if (data == NULL)
    {
        printf("Failed to get 'data' from history object.\n");
        return;
    }

    // 获取key值
    cJSON *key = cJSON_GetObjectItem(data, "key");
    if (key == NULL)
    {
        printf("Failed to get 'key' from data object.\n");
        return;
    }

    // 获取limit数组
    cJSON *limit = cJSON_GetObjectItem(data, "limit");
    if (limit == NULL || cJSON_GetArraySize(limit) < 2)
    {
        printf("Failed to get valid 'limit' array from data object.\n");
        return;
    }

    // 获取时间范围
    cJSON *min_item = cJSON_GetArrayItem(limit, 0);
    cJSON *max_item = cJSON_GetArrayItem(limit, 1);

    if (min_item == NULL || max_item == NULL)
    {
        printf("Invalid limit values\n");
        return;
    }

    int MIN = min_item->valueint; // 最小值
    int MAX = max_item->valueint; // 最大值

    printf("查询历史数据: key=%d, 时间范围=%d-%d\n", key->valueint, MIN, MAX);

    cJSON *report = cJSON_CreateObject();                  // 创建上报对象
    cJSON_AddNumberToObject(report, "type", 3);            // 设置上报类型
    cJSON_AddNumberToObject(report, "key", key->valueint); // 设置设备标识
    cJSON *data_arr = cJSON_CreateArray();                 // 创建数据数组

    // 打开数据库
    if (sqlite3_open(data_db_path, &db) != SQLITE_OK)
    {
        fprintf(stderr, "Database open error: %s\n", sqlite3_errmsg(db));
        cJSON_AddNumberToObject(report, "result", 1);
        char *report_str = cJSON_Print(report);
        send_history_report_directly(report_str);
        free(report_str);
        cJSON_Delete(report);
        return;
    }

    // 创建表（如果不存在）
    const char *create_table_sql = "CREATE TABLE IF NOT EXISTS data_manage (key INT, value TEXT, time long)";
    if (sqlite3_exec(db, create_table_sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        cJSON_AddNumberToObject(report, "result", 1);
        fprintf(stderr, "Create table error: %s\n", errmsg);
        sqlite3_free(errmsg);
        sqlite3_close(db);
        char *report_str = cJSON_Print(report);
        send_history_report_directly(report_str);
        free(report_str);
        cJSON_Delete(report);
        return;
    }
    else
    {
        cJSON_AddNumberToObject(report, "result", 0);
    }

    // 查询数据
    snprintf(sql, sizeof(sql), "SELECT * FROM data_manage WHERE key = %d AND time >= %d AND time <= %d",
             key->valueint, MIN, MAX);

    printf("执行SQL: %s\n", sql);

    if (sqlite3_exec(db, sql, report_callback, data_arr, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "Query data error: %s\n", errmsg);
        sqlite3_free(errmsg);
        cJSON_AddNumberToObject(report, "result", 1);
    }
    else
    {
        // 检查是否有数据
        if (cJSON_GetArraySize(data_arr) == 0)
        {
            printf("没有找到匹配的历史数据\n");
        }
        else
        {
            printf("找到 %d 条历史数据\n", cJSON_GetArraySize(data_arr));
        }
    }

    cJSON_AddItemToObject(report, "data", data_arr); // 添加数据数组
    char *report_str = cJSON_Print(report);
    printf("历史上报: %s\n", report_str);

    // 直接发送历史上报数据
    send_history_report_directly(report_str);

    // 清理资源
    free(report_str);
    cJSON_Delete(report);
    sqlite3_close(db);
}